
#ifndef _MODULO_HASH_H_
#define _MODULO_HASH_H_

#include <math.h>
#include <string>
using std::string;

template <class T>
struct ModuloHash
{};

/**
* modulo hash for int
*/
template <>
struct ModuloHash<int>
{
	size_t operator()(const int& X, size_t S)
	{
		return (size_t(X) % S);
	}
};

/**
* modulo hash for short
*/
template <>
struct ModuloHash<short>
{
	size_t operator()(const short& X, size_t S)
	{
		return size_t(X % S);
	}
};

/**
* modulo hash for unsigned short
*/

template <>
struct ModuloHash<unsigned short>
{
	size_t operator()(const unsigned short& X, size_t S)
	{
		return size_t(X % S);
	}
};


/**
* modulo hash for unsigned int
*/
template <>
struct ModuloHash<unsigned int>
{
	size_t operator()(const unsigned int& X, size_t S)
	{
		return (X % S);
	}
};

/**
* modulo hash for long
*/
template <>
struct ModuloHash<long>
{
	size_t operator()(const long& X, size_t S)
	{
		return size_t(X % S);
	}
};


/**
* modulo hash for unsigned long
*/
template <>
struct ModuloHash<unsigned long>
{
	size_t operator()(const unsigned long& X, size_t S)
	{
		return (X % S);
	}
};

/**
* modulo hash for char string
*/
template <>
struct ModuloHash<char*>
{
	size_t operator()(const char* Y, size_t S)
	{
		char* X = const_cast<char*>(Y);
		unsigned long hash = 5381;
		int c;
		while((c = *X++))
			hash = ((hash << 5) + hash) + c;
		return (hash%S);
	}
};


/**
* modulo hash for stl string
*/
template <>
struct ModuloHash<string>
{
	size_t operator()(const string& Y, size_t S)
	{
		ModuloHash<char*> hasher;
		return hasher(Y.c_str(), S);
	}
};


/**
* modulo hash for double
*/
template <>
struct ModuloHash<double>
{
	size_t operator()(const double& Y, size_t S)
	{
		double X = Y;
		unsigned long hash = 5381;
		X = X - floor(X);
		return size_t((int)(X * hash) % S);
	}
};

/**
* modulo hash for float
*/
template <>
struct ModuloHash<float>
{
	size_t operator()(const float& Y, size_t S)
	{
		float X = Y;
		unsigned long hash = 5381;
		X = X - floor(X);
		return size_t((int)(X * hash) % S);
	}
};



/**
* modulo hash for long double
*/
template <>
struct ModuloHash<long double>
{
	size_t operator()(const long double& Y, size_t S)
	{
		long double X = Y;
		unsigned long hash = 5381;
		X = X - floor(X);
		return size_t((int)(X * hash) % S);
	}
};



template <class Config_>
struct SimpleModuloHash
{
	typedef Config_ Config;
	typedef typename Config::KeyType key_type;

	size_t operator()(const key_type& k)
	{
		ModuloHash<key_type> hasher;
		return hasher(k, Config::max_size);
	}
};


#endif // _MODULO_HASH_H_
